"""
数据迭代器模式实现
用于医疗数据的高效遍历和批量处理
"""

from abc import ABC, abstractmethod
from typing import Iterator, List, Any, Optional, Dict
from django.db.models import QuerySet
from django.core.paginator import Paginator
from Home.models import Doctor, Appointment, MedicalArticle, HealthRecord


class DataIterator(ABC):
    """抽象迭代器接口"""
    
    @abstractmethod
    def __iter__(self):
        pass
    
    @abstractmethod
    def __next__(self):
        pass


class BatchDataIterator(DataIterator):
    """批量数据迭代器 - 用于大数据集的分批处理"""
    
    def __init__(self, queryset: QuerySet, batch_size: int = 100):
        self.queryset = queryset
        self.batch_size = batch_size
        self.current_batch = 0
        self.total_count = queryset.count()
        self.total_batches = (self.total_count + batch_size - 1) // batch_size
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current_batch >= self.total_batches:
            raise StopIteration
        
        start_index = self.current_batch * self.batch_size
        end_index = min(start_index + self.batch_size, self.total_count)
        
        batch_data = list(self.queryset[start_index:end_index])
        self.current_batch += 1
        
        return {
            'batch_number': self.current_batch,
            'total_batches': self.total_batches,
            'data': batch_data,
            'count': len(batch_data)
        }


class DoctorIterator(DataIterator):
    """医生数据迭代器 - 按科室或状态遍历"""
    
    def __init__(self, department_id: Optional[int] = None, status: str = 'active',
                 min_rating: Optional[float] = None, max_fee: Optional[float] = None):
        self.queryset = Doctor.objects.filter(status=status)
        if department_id:
            self.queryset = self.queryset.filter(department_id=department_id)
        if min_rating is not None:
            self.queryset = self.queryset.filter(rating__gte=min_rating)
        if max_fee is not None:
            self.queryset = self.queryset.filter(consultation_fee__lte=max_fee)
        
        self.doctors = list(self.queryset.select_related('department'))
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index >= len(self.doctors):
            raise StopIteration
        
        doctor = self.doctors[self.index]
        self.index += 1
        
        return {
            'id': doctor.id,
            'name': doctor.name,
            'title': doctor.get_title_display(),
            'specialty': ', '.join(doctor.specialties) if isinstance(doctor.specialties, list) else str(doctor.specialties or ''),
            'department': {
                'id': doctor.department.id if doctor.department else None,
                'name': doctor.department.name if doctor.department else '未分科室'
            },
            'hospital': doctor.hospital or '未知医院',
            'rating': float(doctor.rating) if doctor.rating else 0.0,
            'consultation_fee': float(doctor.consultation_fee) if doctor.consultation_fee else 0.0,
            'experience_years': doctor.experience_years,
            'status': doctor.status,
            'is_featured': doctor.is_featured,
            'introduction': doctor.introduction or ''
        }


class AppointmentIterator(DataIterator):
    """预约数据迭代器 - 按用户或医生遍历"""
    
    def __init__(self, user_id: Optional[int] = None, doctor_id: Optional[int] = None, 
                 status: Optional[str] = None):
        self.queryset = Appointment.objects.all()
        
        if user_id:
            self.queryset = self.queryset.filter(user_id=user_id)
        if doctor_id:
            self.queryset = self.queryset.filter(doctor_id=doctor_id)
        if status:
            self.queryset = self.queryset.filter(status=status)
        
        self.appointments = list(self.queryset.select_related('user', 'doctor', 'doctor__department'))
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index >= len(self.appointments):
            raise StopIteration
        
        appointment = self.appointments[self.index]
        self.index += 1
        
        return {
            'appointment_no': appointment.appointment_no,
            'user': appointment.user.username,
            'doctor': {
                'name': appointment.doctor.name,
                'department': appointment.doctor.department.name,
                'title': appointment.doctor.get_title_display()
            },
            'appointment_date': appointment.appointment_date.isoformat(),
            'status': appointment.get_status_display(),
            'fee': float(appointment.fee),
            'symptoms': appointment.symptoms
        }


class HealthRecordIterator(DataIterator):
    """健康档案迭代器 - 按用户和时间范围遍历"""
    
    def __init__(self, user_id: int, record_type: Optional[str] = None, 
                 start_date=None, end_date=None):
        self.queryset = HealthRecord.objects.filter(user_id=user_id)
        
        if record_type:
            self.queryset = self.queryset.filter(record_type=record_type)
        if start_date:
            self.queryset = self.queryset.filter(record_date__gte=start_date)
        if end_date:
            self.queryset = self.queryset.filter(record_date__lte=end_date)
        
        self.records = list(self.queryset.order_by('-record_date'))
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index >= len(self.records):
            raise StopIteration
        
        record = self.records[self.index]
        self.index += 1
        
        return {
            'id': record.id,
            'record_type': record.record_type,
            'value': record.value,
            'unit': record.unit,
            'record_date': record.record_date.isoformat(),
            'notes': record.notes
        }


class KnowledgeArticleIterator(DataIterator):
    """知识库文章迭代器"""
    
    def __init__(self, category: Optional[str] = None, status: str = 'published'):
        self.queryset = MedicalArticle.objects.filter(status=status)
        
        if category:
            self.queryset = self.queryset.filter(category=category)
        
        self.articles = list(self.queryset.select_related('author', 'author__department'))
        self.index = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.index >= len(self.articles):
            raise StopIteration
        
        article = self.articles[self.index]
        self.index += 1
        
        return {
            'id': article.id,
            'title': article.title,
            'summary': article.summary,
            'author': article.author.name,
            'category': article.category,
            'tags': article.tags,
            'view_count': article.view_count,
            'like_count': article.like_count,
            'published_at': article.published_at.isoformat() if article.published_at else None
        }


class PaginatedIterator(DataIterator):
    """分页迭代器 - 用于将数据集分页处理"""
    
    def __init__(self, data_list: List[Any], page_size: int = 10):
        self.data_list = data_list or []  # 防止 None 值
        self.page_size = max(1, page_size)  # 确保页面大小至少为1
        self.total_items = len(self.data_list)
        self.total_pages = max(1, (self.total_items + self.page_size - 1) // self.page_size) if self.total_items > 0 else 1
        self.current_page = 0
        
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current_page >= self.total_pages:
            raise StopIteration
        
        # 处理空数据情况
        if self.total_items == 0:
            result = {
                'page': 1,
                'totalPages': 1,
                'data': [],
                'hasNext': False,
                'hasPrev': False,
                'totalItems': 0
            }
            self.current_page += 1
            return result
            
        start_index = self.current_page * self.page_size
        end_index = min(start_index + self.page_size, self.total_items)
        
        page_data = self.data_list[start_index:end_index]
        
        result = {
            'page': self.current_page + 1,  # 页码从1开始
            'totalPages': self.total_pages,
            'data': page_data,
            'hasNext': self.current_page < self.total_pages - 1,
            'hasPrev': self.current_page > 0,
            'totalItems': self.total_items
        }
        
        self.current_page += 1
        return result
    
    def goToPage(self, page_number: int):
        """跳转到指定页码 (从0开始)"""
        if 0 <= page_number < self.total_pages:
            self.current_page = page_number
        else:
            self.current_page = self.total_pages  # 超出范围，设为结束状态
    
    def reset(self):
        """重置到第一页"""
        self.current_page = 0


# 迭代器工厂类
class MedicalDataIteratorFactory:
    """医疗数据迭代器工厂"""
    
    @staticmethod
    def create_doctor_iterator(department_id: Optional[int] = None, 
                             status: str = 'active',
                             min_rating: Optional[float] = None,
                             max_fee: Optional[float] = None) -> DoctorIterator:
        """创建医生迭代器"""
        return DoctorIterator(department_id, status, min_rating, max_fee)
    
    @staticmethod
    def create_appointment_iterator(user_id: Optional[int] = None, 
                                  doctor_id: Optional[int] = None,
                                  status: Optional[str] = None) -> AppointmentIterator:
        """创建预约迭代器"""
        return AppointmentIterator(user_id, doctor_id, status)
    
    @staticmethod
    def create_health_record_iterator(user_id: int, 
                                    record_type: Optional[str] = None,
                                    start_date=None, 
                                    end_date=None) -> HealthRecordIterator:
        """创建健康档案迭代器"""
        return HealthRecordIterator(user_id, record_type, start_date, end_date)
    
    @staticmethod
    def create_knowledge_iterator(category: Optional[str] = None, 
                                status: str = 'published') -> KnowledgeArticleIterator:
        """创建知识库迭代器"""
        return KnowledgeArticleIterator(category, status)
    
    @staticmethod
    def create_batch_iterator(queryset: QuerySet, 
                            batch_size: int = 100) -> BatchDataIterator:
        """创建批量数据迭代器"""
        return BatchDataIterator(queryset, batch_size)
    
    @staticmethod
    def create_paginated_iterator(data_list: List[Any], 
                                page_size: int = 10) -> PaginatedIterator:
        """创建分页迭代器"""
        return PaginatedIterator(data_list, page_size)


# 使用示例装饰器
def iterate_data(iterator_type: str, **kwargs):
    """数据迭代装饰器"""
    def decorator(func):
        def wrapper(*args, **func_kwargs):
            # 根据类型创建相应的迭代器
            factory = MedicalDataIteratorFactory()
            
            if iterator_type == 'doctor':
                iterator = factory.create_doctor_iterator(**kwargs)
            elif iterator_type == 'appointment':
                iterator = factory.create_appointment_iterator(**kwargs)
            elif iterator_type == 'health_record':
                iterator = factory.create_health_record_iterator(**kwargs)
            elif iterator_type == 'knowledge':
                iterator = factory.create_knowledge_iterator(**kwargs)
            else:
                raise ValueError(f"Unknown iterator type: {iterator_type}")
            
            # 将迭代器作为参数传递给函数
            return func(iterator, *args, **func_kwargs)
        return wrapper
    return decorator 